﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using JEdwonTune.Lib.Hibernate;
using JEdwonTune.Lib;
using System.Xml;
using System.IO;

namespace JEdwonTune.Hibernate {
    public partial class FrmDbConenct : Form {
        private XmlDocument doc = new XmlDocument();
        private String filepath = System.Environment.CurrentDirectory+"\\dbconnection.data";
        private DbHandler _Handler;
        public DbHandler Handler {
            set { _Handler = value; }
            get { return _Handler; }
        }
        public FrmDbConenct() {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) {
            _Handler = new DbHandler();
            _Handler.Addr = this.txtAddr.Text;
            _Handler.DbService = (DbServerType)Enum.Parse(typeof(DbServerType), this.cbxDbServerType.SelectedValue.ToString());
            try {
                _Handler.Port = Convert.ToInt32(this.txtPort.Text);
            } catch {
                MessageBox.Show("端口号请输入一个有效的整数");
                return;
            }
            _Handler.Pwd = this.txtPwd.Text;
            _Handler.SourceName = this.txtDataSource.Text;
            _Handler.User = this.txtUser.Text;
            if (_Handler.TestConnection()) {
                this.DialogResult = DialogResult.OK;
                this.Close();
            } else {
                MessageBox.Show(_Handler.ErrMessage, "数据库链接失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            DoSave();
        }

        private void FrmDbConenct_Load(object sender, EventArgs e) {
            this.dataGridView1.AutoGenerateColumns = false;
            
            this.cbxDbServerType.DisplayMember = "Value";
            this.cbxDbServerType.ValueMember = "Key";
            this.cbxDbServerType.DataSource = Ctrls.DbServerType();

            if (_Handler != null) {
                this.cbxDbServerType.SelectedValue = (int)_Handler.DbService;
                this.txtAddr.Text = _Handler.Addr;
                this.txtDataSource.Text = _Handler.SourceName;
                this.txtPort.Text = _Handler.Port.ToString();
                this.txtPwd.Text = _Handler.Pwd;
                this.txtUser.Text = _Handler.User;
            }

            try {
                if (File.Exists(filepath)) {
                    doc.Load(filepath);
                } else {
                    doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><connections></connections>");
                }
            } catch(Exception ex) {
                MessageBox.Show("无法解析文件：\n"+ex.Message, "加载链接配置文件时出现错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                doc = null;
                return;
            }
            LoadConnectionData();
        }

        private void LoadConnectionData() {
            if (doc == null) {
                MessageBox.Show("无法打开文件", "保存链接配置文件时时出现错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            XmlNodeList conns = doc.SelectNodes("//connection");
            IList<DbHandler> list = new List<DbHandler>();
            foreach (XmlNode n in conns) {
                DbHandler db = new DbHandler();
                db.Addr = GetChildNodeAttr(n, "addr", "");
                db.DbService = ParseDbServerType(GetChildNodeAttr(n, "dbservice", ""));
                db.Port = Convert.ToInt32(GetChildNodeAttr(n, "port", "0"));
                db.Pwd = GetChildNodeAttr(n, "pwd", "");
                db.SourceName = GetChildNodeAttr(n, "sourcename", "");
                db.User = GetChildNodeAttr(n, "user", "");
                list.Add(db);
            }
            this.dataGridView1.DataSource = list;
        }
        private DbServerType ParseDbServerType(String val) {
            try {
                return (DbServerType)Enum.Parse(typeof(DbServerType), val);
            }catch{
                return DbServerType.Oracle10g;
            }
        }
        private void SetChildNodeAttr(ref XmlNode n, String attrName, String val) {
            if (n == null) return;
            if (n.Attributes[attrName] == null) {
                XmlAttribute attr = doc.CreateAttribute(attrName);
                attr.Value = val;
                n.Attributes.Append(attr);
            } else {
                n.Attributes[attrName].Value = val;
            }
        }
        private String GetChildNodeAttr(XmlNode n,String attr,String def) {
            if (n != null && n.Attributes[attr]!=null) {
                return n.Attributes[attr].Value;
            } else {
                return def;
            }
        }

        private void cbxDbServerType_SelectedValueChanged(object sender, EventArgs e) {
            Object val = this.cbxDbServerType.SelectedValue;
            if (val==null || val.GetType() != typeof(String)) return;
            DbServerType service = ParseDbServerType(val.ToString());
            switch (service) {
                case DbServerType.Oracle10g:
                    this.txtPort.Enabled = true;
                    this.txtAddr.Enabled = true;
                    this.txtUser.Enabled = true;
                    this.btnSelectDbFile.Visible = false;
                    this.txtPort.Text = "1521";
                    this.txtUser.Text = "root";
                    this.txtAddr.Text = "localhost";
                    break;
                case DbServerType.MySql6:
                    this.txtPort.Enabled = true;
                    this.txtAddr.Enabled = true;
                    this.txtUser.Enabled = true;
                    this.btnSelectDbFile.Visible = false;
                    this.txtPort.Text = "3306";
                    this.txtUser.Text = "root";
                    this.txtAddr.Text = "localhost";
                    break;
                case DbServerType.SqlServer:
                    this.txtPort.Enabled = true;
                    this.txtAddr.Enabled = true;
                    this.txtUser.Enabled = true;
                    this.btnSelectDbFile.Visible = false;
                    this.txtPort.Text = "1433";
                    this.txtUser.Text = "sa";
                    this.txtAddr.Text = "localhost";
                    break;
                case DbServerType.Sqlite3:
                    this.txtPort.Text = "0";
                    this.txtPort.Enabled = false;
                    this.txtAddr.Text = "#";
                    this.txtAddr.Enabled = false;
                    this.txtUser.Text = "";
                    this.txtUser.Enabled = false;
                    this.txtDataSource.Text = "";
                    this.btnSelectDbFile.Visible = true;
                    break;
                default:
                    break;
            }
        }

        private void DoSave() {
            if (doc == null) {
                MessageBox.Show("无法打开保存文件", "保存时出现错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            XmlNode n = doc.SelectSingleNode("//connection[@addr='" + this.txtAddr.Text
                + "' and @dbservice='" + this.cbxDbServerType.SelectedValue.ToString()
                + "' and @sourcename='" + this.txtDataSource.Text
                +"' and @port='"+this.txtPort.Text+"']");
            if (n == null) {//save 
                XmlNode conn = doc.CreateElement("connection");
                doc.DocumentElement.AppendChild(conn);
                SetChildNodeAttr(ref conn, "addr", this.txtAddr.Text);
                SetChildNodeAttr(ref conn, "sourcename", this.txtDataSource.Text);
                SetChildNodeAttr(ref conn, "port", this.txtPort.Text);
                SetChildNodeAttr(ref conn, "pwd", this.txtPwd.Text);
                SetChildNodeAttr(ref conn, "user", this.txtUser.Text);
                SetChildNodeAttr(ref conn, "dbservice", this.cbxDbServerType.SelectedValue.ToString());
            } else {
                SetChildNodeAttr(ref n, "pwd", this.txtPwd.Text);
                SetChildNodeAttr(ref n, "user", this.txtUser.Text);
            }
            doc.Save(filepath);
            LoadConnectionData();
        }

        private void btnSave_Click(object sender, EventArgs e) {
            DoSave();
        }

        private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e) {
            XmlNode n = doc.DocumentElement.ChildNodes[e.RowIndex];
            if (n == null) return;
            this.cbxDbServerType.SelectedValue = GetChildNodeAttr(n, "dbservice", "");
            this.txtAddr.Text = GetChildNodeAttr(n, "addr", "");
            this.txtPort.Text =GetChildNodeAttr(n, "port", "0");
            this.txtPwd.Text = GetChildNodeAttr(n, "pwd", "");
            this.txtDataSource.Text = GetChildNodeAttr(n, "sourcename", "");
            this.txtUser.Text = GetChildNodeAttr(n, "user", "");
        }

        private void btnDelete_Click(object sender, EventArgs e) {
            DialogResult dr = MessageBox.Show("确定要删除？", "确认", MessageBoxButtons.YesNo);
            if (dr == DialogResult.Yes) {
                foreach (DataGridViewRow row in this.dataGridView1.SelectedRows) {
                    doc.DocumentElement.RemoveChild(doc.DocumentElement.ChildNodes[row.Index]);
                }
                doc.Save(filepath);
                LoadConnectionData();
            }
        }

        private void btnCancel_Click(object sender, EventArgs e) {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }


        private void button1_Click_1(object sender, EventArgs e) {
            Object val = this.cbxDbServerType.SelectedValue;
            DbServerType service = ParseDbServerType(val.ToString());
            if (service == DbServerType.Sqlite3) {
                DialogResult dr = this.openFileDialog1.ShowDialog();
                if (dr == DialogResult.OK) {
                    this.txtDataSource.Text = this.openFileDialog1.FileName;
                }
            }
        }
    }
}
